﻿#include "channelinfo.h"
#include <QPixmap>
#include <librtc.h>
#include "clientcallback.h"
#include "globaltools.h"

BaseChannelInfo::BaseChannelInfo() : mute(false), unread_count(0)
{

}

quintptr BaseChannelInfo::internalId() const
{
    return reinterpret_cast<quintptr>(this);
}

const BaseChannelInfo *BaseChannelInfo::fromInternalId(quintptr iId)
{
    return reinterpret_cast<const BaseChannelInfo *>(iId);
}

qint64 BaseChannelInfo::uniqueId() const
{
    return makeUniqueId(id(), isP2P());
}

qint64 BaseChannelInfo::idFromUniqueId(const qint64 &unique)
{
    return unique >> 1;
}

bool BaseChannelInfo::isP2PFromUniqueId(const qint64 &unique)
{
    return unique & 1;
}

QPair<bool, qint64> BaseChannelInfo::fromUniqueId(const qint64 &unique)
{
    return QPair<bool, qint64>(isP2PFromUniqueId(unique), idFromUniqueId(unique));
}

qint64 BaseChannelInfo::makeUniqueId(const qint64 &id, bool isP2P)
{
    return id << 1 | qint64(isP2P);
}

bool BaseChannelInfo::equals(const qint64 &unique, const qint64 &id, bool isP2P)
{
    return unique > 0 && isP2PFromUniqueId(unique) == isP2P && idFromUniqueId(unique) == id;
}

QVariantHash &BaseChannelInfo::create_msg(qint64 msg_time, const QByteArray &mid)
{
    auto it = msg_list.find(mid);
    if(it == msg_list.end())
    {
        //新的
        auto &msg = msg_list[mid];
        setParam(msg, cmd_param_msg_time, msg_time);
        msg_index.insert(msg_time, &msg);
        return msg;
    }
    //旧的
    const qint64 old_time = getParam(it.value(), cmd_param_msg_time).toLongLong();
    if(msg_time != old_time)
    {
        msg_index.remove(old_time, it.operator->());
        msg_index.insert(msg_time, it.operator->());
        setParam(it.value(), cmd_param_msg_time, msg_time);
    }
    return it.value();
}

bool BaseChannelInfo::add_msg_list(const QByteArray &mid, QVariantHash &msg, bool isRead)
{
    int type = getParam(msg, cmd_param_msg_type).toInt();
    if(!isVisibleMsg(type, false))
        return false;
    if(getParam(msg, cmd_param_snd_name).toString() == getParam(msg, cmd_param_snd_id).toString())
        removeParam(msg, cmd_param_snd_name);
    if(getParam(msg, cmd_param_snd_name).toString().isEmpty())
    {
        QString name = getMemberName(getParam(msg, cmd_param_snd_id).toLongLong());
        if(!name.isEmpty())
            setParam(msg, cmd_param_snd_name, name);
    }
    const qint64 msg_time = getParam(msg, cmd_param_msg_time).toLongLong();
    auto it = msg_list.find(mid);
    if(it == msg_list.end())
    {
        //新的
        msg_index.insert(msg_time, &(msg_list[mid] = msg));
        if(isUnreadMsg(msg))
        {
            if(isRead){
                setParam(msg, cmd_param_state, msg_state_readed);
                call_mark_read(mid);
            }
            else
                unread_count++;
        }
        return true;
    }
    //旧的
    const qint64 old_time = getParam(it.value(), cmd_param_msg_time).toLongLong();
    it.value() = msg;
    if(msg_time != old_time)
    {
        msg_index.remove(old_time, it.operator->());
        msg_index.insert(msg_time, it.operator->());
    }
    return false;
}

QByteArrayList BaseChannelInfo::mark_read(const QByteArray &mid)
{
    QByteArrayList mids;
    if(mid.isEmpty())
    {
        for(auto it = msg_list.begin(); it != msg_list.end(); it++)
        {
            auto &msg = it.value();
            if(isUnreadMsg(msg))
            {
                setParam(msg, cmd_param_state, msg_state_readed);
                mids.append(it.key());
            }
        }
        unread_count = 0;
    }
    else
    {
        auto it = msg_list.find(mid);
        if(it != msg_list.end())
        {
            auto &msg = it.value();
            if(isUnreadMsg(msg))
            {
                setParam(msg, cmd_param_state, msg_state_readed);
                mids.append(it.key());
                if(unread_count > 0)
                    --unread_count;
            }
        }
    }
    return mids;
}

bool BaseChannelInfo::mark_peer_read(const QByteArray &mid)
{
    auto it = msg_list.find(mid);
    if(it != msg_list.end() )
    {
        auto &msg = it.value();
        if(getParam(msg, cmd_param_direction).toInt() == msg_dir_send && getParam(msg, cmd_param_state).toInt() != msg_state_peer_read)
        {
            setParam(msg, cmd_param_state, msg_state_peer_read);
            return true;
        }
    }
    return false;
}

QList<QVariantHash> BaseChannelInfo::get_msg_list() const
{
    QList<QVariantHash> res;
    res.reserve(msg_index.size());
    for(auto it = msg_index.constBegin(); it != msg_index.constEnd(); it++)
        if(isVisibleMsg(*(it.value()), true))
            res.append(*(it.value()));
    ;
    return res;
}

void BaseChannelInfo::clear_msg_list()
{
    msg_index.clear();
    msg_list.clear();
}

qint64 BaseChannelInfo::last_msg_time() const
{
    if(msg_index.isEmpty())
        return 0;
    return msg_index.lastKey();
}

QString BaseChannelInfo::last_msg() const
{
    if(msg_index.isEmpty())
        return QString();
    auto &msg = *(msg_index.last());
    QString content;
    int msg_type = getParam(msg, cmd_param_msg_type).toInt();
    if(msg_type == msg_type_image)
        content = QObject::trECSUTF8("[图片]");
    else if(msg_type == msg_type_audio)
        content = QObject::trECSUTF8("[语音](目前电脑端不支持播放)");
    else if(msg_type == msg_type_video)
        content = QObject::trECSUTF8("[视频](目前电脑端不支持播放)");
    else if(msg_type == msg_type_text)
        content = getParam(msg, cmd_param_msg).toString();
    else if(msg_type == msg_type_notify)
    {
        content = getParam(msg, cmd_param_msg).toString();
        if(content == P2PChanneInfo::start_talk)
            content = QObject::trECSUTF8("开始对讲");
        else if(content == P2PChanneInfo::end_talk)
            content = QObject::trECSUTF8("结束对讲");
    }
    else if(msg_type == msg_type_dispatch_start)
        content = QObject::trECSUTF8("分享视频");
    else if(msg_type == msg_type_dispatch_end)
        content = QObject::trECSUTF8("结束视频");
    if(!content.isEmpty())
    {
        auto from = getParam(msg, cmd_param_snd_name).toString();
        if(from.isEmpty())
        {
            if(auto snd_id = getParam(msg, cmd_param_snd_id).toLongLong())
            {
                from = getMemberName(snd_id);
                if(from.isEmpty())
                    from = QString::number(snd_id);
                else
                    setParam(msg, cmd_param_snd_name, from);
            }
        }
        if(!from.isEmpty())
            from.append(':');
        return from + content;
    }
    return content;
}

QString BaseChannelInfo::getMemberName(qint64 uid) const
{
    for(auto it = member_list.constBegin(); it != member_list.constEnd(); it++)
    {
        if(getParam(*it, cmd_param_uid).toLongLong() == uid)
        {
            return getParam(*it, cmd_param_name).toString();
        }
    }
    return QString();
}

bool BaseChannelInfo::msg_less_than(const QVariantHash &left, const QVariantHash &right)
{
    return getParam(left, cmd_param_msg_time).toLongLong() < getParam(right, cmd_param_msg_time).toLongLong();
}

bool BaseChannelInfo::isVisibleMsg(const QVariantHash &msg, bool inChat)
{
    return isVisibleMsg(getParam(msg, cmd_param_msg_type).toInt(), inChat);
}

bool BaseChannelInfo::isVisibleMsg(const int type, bool inChat)
{
    if(type == msg_type_text || type == msg_type_image || type == msg_type_audio || type == msg_type_video)
        return true;
    if(inChat)
        return false;
    //以下可在列表显示
    return type == msg_type_notify || type == msg_type_dispatch_start || type == msg_type_dispatch_end;
}

bool BaseChannelInfo::isUnreadMsg(const QVariantHash &msg)
{
    return isUnreadMsg(getParam(msg, cmd_param_msg_type).toInt(), msg);
}

bool BaseChannelInfo::isUnreadMsg(const int type, const QVariantHash &msg)
{
    return isVisibleMsg(type, true) && getParam(msg, cmd_param_direction).toInt() == msg_dir_recv && getParam(msg, cmd_param_state).toInt() == msg_state_recv;
}

ChannelInfo::ChannelInfo(qint64 id) : rid(id)
{
}

ChannelInfo::ChannelInfo(qint64 id, QVariantHash &info) : ChannelInfo(id)
{
    rname = getParam(info, cmd_param_name).toString();
    rstyle = getParam(info, cmd_param_style).toInt();
}

bool ChannelInfo::isP2P() const
{
    return false;
}

qint64 ChannelInfo::id() const
{
    return rid;
}

qint64 ChannelInfo::getRid() const
{
    return rid;
}

QString ChannelInfo::display() const
{
    return rname;
}

QVariant ChannelInfo::decoration() const
{
    int style = 0;
    if(rstyle == 4)
        style = mute ? 7 : 6;  //temp
    else if(mute)
        style = 3;  //mute
    else if(rstyle >= 90 && rstyle < 100)
        style = 2;  //red
    else
        style = 1;  //talk
    if(style > 0)
        return QPixmap(QLatin1Literal(":/gui/room_logo")+QString::number(style)+QLatin1Literal(".png"));
    return QVariant();
}

void ChannelInfo::call_mark_read(const QByteArray &mid) const
{
    ClientCallback::instance()->channel_mark_read(rid, mid);
}

void ChannelInfo::call_mark_read_all(qint64 rid, const QByteArrayList &mids)
{
    if(mids.size() == 1)
        ClientCallback::instance()->channel_mark_read(rid, mids.first());
    else
        ClientCallback::instance()->channel_mark_read(rid);
}

const QString P2PChanneInfo::start_talk = "1";
const QString P2PChanneInfo::end_talk = "0";

bool P2PChanneInfo::isP2P() const
{
    return true;
}

qint64 P2PChanneInfo::id() const
{
    return uid;
}

qint64 P2PChanneInfo::getRid() const
{
    return p2pchannel_room_id;
}

QString P2PChanneInfo::display() const
{
    return name;
}

QVariant P2PChanneInfo::decoration() const
{
    return icon;
}

void P2PChanneInfo::call_mark_read(const QByteArray &mid) const
{
    //1.mark read
    ClientCallback::instance()->im_mark_read(uid, mid);
    //2.send read
    ClientCallback::instance()->im_send_msg(uid, QString(), msg_type_msg_readed, mid);
}

void P2PChanneInfo::call_mark_read_all(qint64 uid, const QByteArrayList &mids)
{
    if(mids.size() == 1)
    {
        //只有一条要设置时
        //1.mark read
        ClientCallback::instance()->im_mark_read(uid, mids.first());
        //2.send read
        ClientCallback::instance()->im_send_msg(uid, QString(), msg_type_msg_readed,mids.first());
    }
    else
    {
        //1.mark read
        ClientCallback::instance()->im_mark_read(uid);
        //2.send read
        if(!mids.isEmpty())
            ClientCallback::instance()->im_send_msg(uid, QString(), msg_type_msg_readed, mids.join(','));
    }
}
